#ifndef MAP_H
#define MAP_H



#include "AStar.h"


/*!
 * \file Map.h
 * \brief Gestion de la map (création de la carte aléatoirement,verif collision)
 * \author Nicolas JAEGER
 * \version 0.1
 */
 /*! \struct CaseProp
  *  \brief Structure destinée qui contient les propriètes d'un carreau sur la carte
  */
struct CaseProp{

            bool accessible;
            bool transparent;
            bool interieur;
            bool vide;

            char display;
        };
/*! \brief Designe les cases de la carte pour relier la struc CaseProp aux tableau prédefini des informations
*/
enum Tile {VIDE,POINT,COULOIR,SPAWN,FIN,MURDROIT,MURHAUT,MURBAS,PORTE,};
/*! \brief Contient les infos des cases
*/
const CaseProp Info[]={{false,false,false,true,' '},
                        {true,true,true,false,'.'},
                        {true,true,false,false,'#'},
                        {true,true,true,false,'>'},
                        {true,true,true,false,'<'},
                        {false,false,false,false,'|'},
                        {false,false,false,false,'_'},
                        {false,false,false,false,'-'},
                        {true,true,false,false,':'}
                        };
enum Type_Edge { ESC_MON,ESC_DES,PORTE1,PORTE2 };
using namespace std;
/*! \class Map
*   \brief Classe destinée à la gestion et à la génération de la carte
*/
class Map
{
    public:

        /*! \struct salle
        * \brief Struct pour une manipulation facile des salles contient la position du point haut-gauche et la taille
        */
        struct salle{
            //Position du point haut-gauche de la salle
            int x;
            int y;
            //Taille de la salle à partir du point précedent
            int tailleX;
            int tailleY;

        };

        Map();

        /*! \brief Méthode de Map
         *  Methode qui genère la carte
         */
        void randomMapGenerator();
        /*! \brief Méthode de Map
         *  Methode qui dessine la position (x,y)
         * \param x position sur l'axe des abscisse
         *        y position sur l'axe des ordonnées
         */
        const void drawPos(int x,int y);
        /*! \brief Méthode de Map
         *  Methode qui renvoie l'accesibilité de la case
         * \param x position sur l'axe des abscisse
         *        y position sur l'axe des ordonnées
         * \return bool rue si la case est accessible par le joueur false sinon
         */
        const bool estAccessible(int x,int y);
        const bool estAccessible(position a,int mov=-1);
        /*! \brief Méthode de Map
         *  Methode qui renvoie la position du spawn
         * \return positio position du spawn
         */
        const position getSpawn();
        /*! \brief Méthode de Map
         *  Methode qui renvoie la position de la fin
         * \return positio position de la fin
         */
        const position getFin();

        /*! \brief Mérthode de Map
         * Renvoie si la position est le spawn ou non
         * \param a position que l'on veut vérifier
         * \return true si oui
         *          false sinon
         */

        const bool isFin(position a);
        /*! \brief Mérthode de Map
         * Renvoie si la position est la fin ou non
         * \param a position que l'on veut vérifier
         * \return true si oui
         *          false sinon
         */
        const bool isSpawn(position a);
        /*! \brief Génère une position aléatoire à l'intérieur des salles en utlisant le vector les contennant toutes
        *   \return position qui contient lla position générer aléatoirement
        */

        const position randomPositionInterieur();
        /*! \brief Retourne la valeur de la propriété Transparence pour la case à la position p
         * \param p  position de la case dont on souhaite obtenir la valeur
         */
        const bool getTransparence(position p);
        /*! \brief Vérifie si la position est à l'interieur d'une salles
         *  \param a position que l'on veut vérifier
         */
        const bool isInterieur(position a);
        /*! \brief Retourne la valeur de la propriété Transparence pour la case à la position p
         * \param x position sur l'axe des abscisse
         *        y position sur l'axe des ordonnées
         */
        const bool getTransparence(int x,int y);
        /*! \brief Vérifie si la position est à l'interieur d'une salles
         * \param x position sur l'axe des abscisse
         *        y position sur l'axe des ordonnées
         */
        const bool isInterieur(int x , int y);
        /*! \brief Verifie si il existe une ligen de vue entre la position a et b
         *      Trace une ligne de bresenham entre les points a et b et s'arrête et retourne false si elle rencontre un objet non transparent
         *
         *   \param a position de depart
        *         b position d'arrivé
        *  \return true si b est visible de a
        *        false sinon
        */
        const bool checkLOS(position a,position b);
        bool isChgt(position a);
        Type_Edge chgtType(position a);
        position getPorte(int a);
        void getCostMap(int  (&costmap)[NY][NX] );
        void getCostMapCouloir(int (&costmap)[NY][NX] );

    protected:
        /*! \brief Ecrit la salles en terme de CaseProp dans le tableau de la map à partir d'une struct salle et ajoute les murs
            \param centre une salle
        */
        void writeSalle(salle centre);
        /*! \brief Verifie si la salle aTester n'écrase pas une salle déjà existante
            \param aTester salle que l'ont veut tester
        */
        const bool testAjoutSalle(salle aTester);
        /*! \brief Cherche le couloir entre debut et fin et le retourne sous forme d'un vector de position (l'algo n'est pas a*=)
          *  \param debut salle de départ
          *          fin salle de fin
          */
        const vector<position> a_star(salle debut,salle fin);
        /*! \brief Créer le spawn
        */
        void creerSpawn();
        /*! \brief Ecrit le chemin décrit par chemin dans le tableau niveau_
            \param chemin Chemin à transposer sur niveau_ (généralement sortie de a_star)
        */
        void writeChemin(vector<position> chemin);
        /*! \brief Retourne la salle la plus proche de ajout dans la liste salles_
            \param ajout salle dont on veut trouver la plus proche
        */
        salle salleLaPlusProche(salle ajout);
        /*! \brief Retourne une salles au dimension et au positionnement aléatoire dans les limites de la map
        */
        const salle salleRandom();
        /*! \brief Créer l'escalier descendant
        */
        void creerFin();
        void creerPortes();
        void addMur();
        void bricolage();



        CaseProp niveau_[NY][NX]; /*< Tableau de int décrivant le niveau suivant les define du début de fichier */
        int nombreDeSalle;   /*< nNombre de salle sur le niveau */
        position spawn_;      /*< Position du spawn */
        position fin_;        /*< Position de la fin  */
        vector<salle> salles_; /*< Contient les salles crées pour le niveau (BUT a long terme pour une génration plus avancé de carte) */
        position porte1_;
        position porte2_;
};

#endif // MAP_H
